﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
using PylonCamera;
using Separate.Model.Vision;
using Commonality.Model;
using Commonality.Model.Tray;

namespace Separate.BLL
{
    public partial class VisionWindow : Form
    {
        public CPylonCamera Camera;
        public string CameraName;
        public HObject m_image;
        private HTuple hv_win;
        private double row, col, phi, lenth1, lenth2, threshold, minarea;  //视觉检测参数
        private double row1Card1, col1Card1, row2Card1, col2Card1, minareaCard1, maxareaCard1;
        private double row1Card2, col1Card2, row2Card2, col2Card2, minareaCard2, maxareaCard2;
        public bool isCaer;
        public VisionWindow(string cameraName)
        {
            InitializeComponent();
            CameraName = cameraName;

            Control.CheckForIllegalCrossThreadCalls = false;
            this.WindowState = FormWindowState.Maximized;
            hv_win = new HTuple();
            hv_win = this.hWindowControl.HalconWindow;
            HOperatorSet.SetPart(hv_win, 0, 0, 3036 - 1, 4024 - 1);

            HObject empty_image;             //开始运行时显示一张空照片，不然halcon会有bug
            HOperatorSet.GenEmptyObj(out empty_image);
            empty_image.Dispose();
            HOperatorSet.ReadImage(out empty_image, Application.StartupPath + "\\Tool\\Empty.bmp");
            HOperatorSet.DispObj(empty_image, hv_win);
            empty_image.Dispose();

            isCaer = false;
        }

        private void VisionWindow_Load(object sender, EventArgs e)
        {
            Camera = new CPylonCamera();
            VisionPamraLoad(CameraName);
        }
        private void VisionPamraLoad(string name)
        {
            try
            {
                row = Convert.ToDouble(OperateIniFile.ReadIniData("Device", name + "row", "", Application.StartupPath + @"\Tool\Device.ini"));
                col = Convert.ToDouble(OperateIniFile.ReadIniData("Device", name + "col", "", Application.StartupPath + @"\Tool\Device.ini"));
                phi = Convert.ToDouble(OperateIniFile.ReadIniData("Device", name + "phi", "", Application.StartupPath + @"\Tool\Device.ini"));
                lenth1 = Convert.ToDouble(OperateIniFile.ReadIniData("Device", name + "lenth1", "", Application.StartupPath + @"\Tool\Device.ini"));
                lenth2 = Convert.ToDouble(OperateIniFile.ReadIniData("Device", name + "lenth2", "", Application.StartupPath + @"\Tool\Device.ini"));
                threshold = Convert.ToDouble(OperateIniFile.ReadIniData("Device", name + "threshold", "", Application.StartupPath + @"\Tool\Device.ini"));
                minarea = Convert.ToDouble(OperateIniFile.ReadIniData("Device", name + "minarea", "", Application.StartupPath + @"\Tool\Device.ini"));
                Log4Net.MsgInfo("加载" + CameraName + "视觉参数");

                row1Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", name + "row1", "", Application.StartupPath + @"\Tool\Device.ini"));
                col1Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", name + "col1", "", Application.StartupPath + @"\Tool\Device.ini"));
                row2Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", name + "row2", "", Application.StartupPath + @"\Tool\Device.ini"));
                col2Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", name + "col2", "", Application.StartupPath + @"\Tool\Device.ini"));
                col2Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", name + "col2", "", Application.StartupPath + @"\Tool\Device.ini"));
                minareaCard1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", name + "minarea", "", Application.StartupPath + @"\Tool\Device.ini"));
                maxareaCard1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", name + "maxarea", "", Application.StartupPath + @"\Tool\Device.ini"));

                row1Card2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", name + "row1", "", Application.StartupPath + @"\Tool\Device.ini"));
                col1Card2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", name + "col1", "", Application.StartupPath + @"\Tool\Device.ini"));
                row2Card2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", name + "row2", "", Application.StartupPath + @"\Tool\Device.ini"));
                col2Card2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", name + "col2", "", Application.StartupPath + @"\Tool\Device.ini"));
                minareaCard2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", name + "minarea", "", Application.StartupPath + @"\Tool\Device.ini"));
                maxareaCard2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", name + "maxarea", "", Application.StartupPath + @"\Tool\Device.ini"));
            }
            catch 
            {
                Log4Net.MsgInfo("加载视觉参数异常");
            }

        }
        public bool OpenCamera()
        {

            return Camera.OpenCamera(CameraName);
        }
        public void CloseCamera()
        {
            Camera.CameraClose();
        }

        public void DispObj()
        {
            HOperatorSet.GenEmptyObj(out m_image);
            m_image.Dispose();
            Camera.GrabOnePic(out m_image);
            HOperatorSet.DispObj(m_image, hv_win);
            m_image.Dispose();
        }


        public HObject m_imageAuto;
        public string Detection(TrayModel trayModel)     //异物检测
        {
            string detection_result = "";

            Tuple<bool, bool> str = new Tuple<bool, bool>(false, false);
            try
            {
                HOperatorSet.GenEmptyObj(out m_imageAuto);
                m_imageAuto.Dispose();
                Camera.GrabOnePic(out m_imageAuto);
                try
                {
                    HOperatorSet.DispObj(m_imageAuto, hv_win);
                }
                catch 
                {
                }
                detection_result = Tray_Detection(m_imageAuto, row, col, phi, lenth1, lenth2, threshold, minarea, trayModel);
                m_imageAuto.Dispose();
                if (true)
                {

                }
        }
            catch
            {
                detection_result = "Err";
            }

            return detection_result;
        }

        private void SaveImage(string type, HObject m_image)   //保存照片
        {
            HOperatorSet.WriteImage(m_image, "tiff", 0, Application.StartupPath + "\\SaveImage\\" + type + "-" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss.fff") + ".tiff");

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Thread.Sleep(10);
            HTuple hv_row1 = null, hv_col1 = null, hv_row2 = null, hv_col2 = null;
            try
            {
                HOperatorSet.DrawRectangle1(hv_win, out hv_row1, out hv_col1, out hv_row2, out hv_col2);
                OperateIniFile.WriteIniData("DeviceCard1", CameraName + "row1", hv_row1.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("DeviceCard1", CameraName + "col1", hv_col1.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("DeviceCard1", CameraName + "row2", hv_row2.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("DeviceCard1", CameraName + "col2", hv_col2.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                row1Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", CameraName + "row1", "", Application.StartupPath + @"\Tool\Device.ini"));
                col1Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", CameraName + "col1", "", Application.StartupPath + @"\Tool\Device.ini"));
                row2Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", CameraName + "row2", "", Application.StartupPath + @"\Tool\Device.ini"));
                col2Card1 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard1", CameraName + "col2", "", Application.StartupPath + @"\Tool\Device.ini"));

                Log4Net.MsgInfo("修改区域成功");
            }
            catch
            {
                Log4Net.MsgInfo("修改区域失败");
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Thread.Sleep(10);
            HTuple hv_row1 = null, hv_col1 = null, hv_row2 = null, hv_col2 = null;
            try
            {
                HOperatorSet.DrawRectangle1(hv_win, out hv_row1, out hv_col1, out hv_row2, out hv_col2);
                OperateIniFile.WriteIniData("DeviceCard2", CameraName + "row1", hv_row1.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("DeviceCard2", CameraName + "col1", hv_col1.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("DeviceCard2", CameraName + "row2", hv_row2.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("DeviceCard2", CameraName + "col2", hv_col2.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                row1Card2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", CameraName + "row1", "", Application.StartupPath + @"\Tool\Device.ini"));
                col1Card2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", CameraName + "col1", "", Application.StartupPath + @"\Tool\Device.ini"));
                row2Card2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", CameraName + "row2", "", Application.StartupPath + @"\Tool\Device.ini"));
                col2Card2 = Convert.ToDouble(OperateIniFile.ReadIniData("DeviceCard2", CameraName + "col2", "", Application.StartupPath + @"\Tool\Device.ini"));
                Log4Net.MsgInfo("修改区域成功");
            }
            catch
            {
                Log4Net.MsgInfo("修改区域失败");
            }
        }

        private string Tray_Detection(HObject image, double row, double col, double phi, double lenth1, double lenth2, double threshold, double min_area, TrayModel trayModel)
        {
            //Tuple<bool, bool> str = new Tuple<bool, bool>(false, false);
            string str = "";
            try
            {
                bool b_model = Find_Model_(image);
                //b_model = false;
                // Local iconic variables 

                HObject ho_Rectangle = null, ho_Rectangle1 = null, ho_Rectangle2 = null, ho_ImageReduced = null;
                HObject ho_Regions = null, ho_RegionOpening = null, ho_ConnectedRegions = null;
                HObject ho_SelectedRegions = null;

                // Local control variables 

                HTuple hv_Number = new HTuple();
                // Initialize local and output iconic variables 
                HOperatorSet.GenEmptyObj(out ho_Rectangle);
                HOperatorSet.GenEmptyObj(out ho_ImageReduced);
                HOperatorSet.GenEmptyObj(out ho_Regions);
                HOperatorSet.GenEmptyObj(out ho_RegionOpening);
                HOperatorSet.GenEmptyObj(out ho_ConnectedRegions);
                HOperatorSet.GenEmptyObj(out ho_SelectedRegions);
                HOperatorSet.GenEmptyObj(out ho_Rectangle1);
                HOperatorSet.GenEmptyObj(out ho_Rectangle2);

                ho_Rectangle.Dispose();
                HOperatorSet.GenRectangle2(out ho_Rectangle, row, col, phi, lenth1, lenth2);
                HOperatorSet.SetColor(hv_win, "red");
                HOperatorSet.SetDraw(hv_win, "margin");
                HOperatorSet.DispObj(ho_Rectangle, hv_win);
                ho_ImageReduced.Dispose();
                HOperatorSet.ReduceDomain(image, ho_Rectangle, out ho_ImageReduced);
                {
                    if (trayModel == TrayModel.X1777)
                    {
                        ho_Rectangle1.Dispose();
                        HOperatorSet.GenRectangle1(out ho_Rectangle1, row1Card1, col1Card1, row2Card1, col2Card1);
                        HOperatorSet.OverpaintRegion(ho_ImageReduced, ho_Rectangle1, 0, "fill");

                        ho_Rectangle2.Dispose();
                        HOperatorSet.GenRectangle1(out ho_Rectangle2, row1Card2, col1Card2, row2Card2, col2Card2);
                        HOperatorSet.OverpaintRegion(ho_ImageReduced, ho_Rectangle2, 0, "fill");
                    }
                }
                ho_Regions.Dispose();
                HOperatorSet.Threshold(ho_ImageReduced, out ho_Regions, threshold, 255);
                ho_RegionOpening.Dispose();
                HOperatorSet.OpeningCircle(ho_Regions, out ho_RegionOpening, 10);
                ho_ConnectedRegions.Dispose();
                HOperatorSet.Connection(ho_RegionOpening, out ho_ConnectedRegions);
                ho_SelectedRegions.Dispose();
                HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, "area", "and", min_area, 99999999);
                HOperatorSet.CountObj(ho_SelectedRegions, out hv_Number);
                if (hv_Number > 0)
                {
                    HOperatorSet.SetDraw(hv_win, "fill");
                    HOperatorSet.DispObj(ho_SelectedRegions, hv_win);

                    //
                    //caer = (hv_Number == 2 &&
                    //        Caer(ho_SelectedRegions, row1Card1, col1Card1, row2Card1, col2Card1, minareaCard1, maxareaCard1)&&
                    //        Caer(ho_SelectedRegions, row1Card2, col1Card2, row2Card2, col2Card2, minareaCard2, maxareaCard2));
                    //
                }
                ho_Rectangle.Dispose();
                ho_Rectangle1.Dispose();
                ho_Rectangle2.Dispose();
                ho_ImageReduced.Dispose();
                ho_Regions.Dispose();
                ho_RegionOpening.Dispose();
                ho_ConnectedRegions.Dispose();
                ho_SelectedRegions.Dispose();
                if (hv_Number != 0 )
                {
                    SaveImage("异物", image);
                    str = "异物";
                }
                else if (b_model)
                {
                    SaveImage("膜", image);
                    str = "膜";                    
                }
                else
                {
                    str = "OK";
                }

            }
            catch
            {
                SaveImage("Catch", image);
                //str = new Tuple<bool, bool>(false, false);
                str = "NG";
            }

            return str;
        }
        private bool Caer(HObject hoj, HTuple hv_row1, HTuple hv_col1, HTuple hv_row2, HTuple hv_col2,HTuple minarea,HTuple maxarea)
        {
            try
            {
                HTuple hv_area = null, hv_col = null, hv_row = null;
                HOperatorSet.AreaCenter(hoj, out hv_area, out hv_row, out hv_col);

                if ((hv_area[0] > minarea && hv_area[0] < maxarea && hv_row[0] > hv_row1 && hv_row[0] < hv_row2 && hv_col[0] > hv_col1 && hv_col[0] < hv_col2)
                    ||
                    (hv_area[1] > minarea && hv_area[1] < maxarea && hv_row[1] > hv_row1 && hv_row[1] < hv_row2 && hv_col[1] > hv_col1 && hv_col[1] < hv_col2))
                {
                    //面积/位置ok
                    return true;
                }
            }
            catch 
            {
            }
            return false;
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            Thread.Sleep(10);
            HTuple hv_row = null, hv_col = null, hv_phi = null, hv_lenth1 = null, hv_lenth2 = null;
            try
            {
                HOperatorSet.DrawRectangle2(hv_win, out hv_row, out hv_col, out hv_phi, out hv_lenth1, out hv_lenth2);
                OperateIniFile.WriteIniData("Device", CameraName +"row", hv_row.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("Device", CameraName + "col", hv_col.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("Device", CameraName + "phi", hv_phi.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("Device", CameraName + "lenth1", hv_lenth1.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                OperateIniFile.WriteIniData("Device", CameraName + "lenth2", hv_lenth2.ToString(), Application.StartupPath + @"\Tool\Device.ini");
                row = Convert.ToDouble(OperateIniFile.ReadIniData("Device", CameraName + "row", "", Application.StartupPath + @"\Tool\Device.ini"));
                col = Convert.ToDouble(OperateIniFile.ReadIniData("Device", CameraName + "col", "", Application.StartupPath + @"\Tool\Device.ini"));
                phi = Convert.ToDouble(OperateIniFile.ReadIniData("Device", CameraName + "phi", "", Application.StartupPath + @"\Tool\Device.ini"));
                lenth1 = Convert.ToDouble(OperateIniFile.ReadIniData("Device", CameraName + "lenth1", "", Application.StartupPath + @"\Tool\Device.ini"));
                lenth2 = Convert.ToDouble(OperateIniFile.ReadIniData("Device", CameraName + "lenth2", "", Application.StartupPath + @"\Tool\Device.ini"));
                Log4Net.MsgInfo("修改区域成功");
            }
            catch
            {
                Log4Net.MsgInfo("修改区域失败");
            }
        }




        private bool Find_Model_(HObject image)
        {
            string Model = "";
            if (CameraName == "CameraA")
            {
                Model = "modelA.shm";
                return Find_ModelA(Model, image);
            }
            else
            {
                Model = "modelB.shm";
                return Find_ModelB(Model, image);
            }
            //return Find_Model(Model, image);


        }
        private static bool Find_ModelB(string model, HObject image)
        {
            try
            {
                // Local iconic variables 

                // Local control variables 
                HObject ho_Rectangle = null, ho_ImageReduced = null;
                HTuple hv_ModelID = null, hv_Row = null, hv_Column = null;
                HTuple hv_Angle = null, hv_Scale = null, hv_Score = null;

                HOperatorSet.GenEmptyObj(out ho_ImageReduced);
                HOperatorSet.GenEmptyObj(out ho_Rectangle);
                ho_Rectangle.Dispose();
                ho_ImageReduced.Dispose();
                HOperatorSet.GenRectangle1(out ho_Rectangle, 350, 1800, 2600, 3200);
                HOperatorSet.ReduceDomain(image, ho_Rectangle, out ho_ImageReduced);
                // Initialize local and output iconic variables 
                HOperatorSet.ReadShapeModel("modelB.shm", out hv_ModelID);
                HOperatorSet.FindScaledShapeModel(ho_ImageReduced, hv_ModelID, -0.39,
                    0.78, 0.9, 1.1, 0.75, 1, 0.5, "least_squares", 0, 0.9, out hv_Row, out hv_Column,
                    out hv_Angle, out hv_Scale, out hv_Score);
                HOperatorSet.ClearShapeModel(hv_ModelID);
                if (hv_Score.Length > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
        }
            catch
            {
                Log4Net.MsgInfo("模板匹配异常");
                return true;
            }


}

        private static bool Find_ModelA(string model, HObject image)
        {
            try
            {
                // Local iconic variables 

                // Local control variables 
                HObject ho_Rectangle = null,ho_ImageReduced = null;
                HTuple hv_ModelID = null, hv_Row = null, hv_Column = null;
                HTuple hv_Angle = null, hv_Scale = null, hv_Score = null;

                HOperatorSet.GenEmptyObj(out ho_ImageReduced);
                HOperatorSet.GenEmptyObj(out ho_Rectangle);
                ho_Rectangle.Dispose();
                ho_ImageReduced.Dispose();
                HOperatorSet.GenRectangle1(out ho_Rectangle, 300, 1800, 2500, 2500);
                HOperatorSet.ReduceDomain(image, ho_Rectangle, out ho_ImageReduced);
                // Initialize local and output iconic variables 
                HOperatorSet.ReadShapeModel("modelA.shm", out hv_ModelID);
            HOperatorSet.FindScaledShapeModel(ho_ImageReduced, hv_ModelID, -0.39,
                0.78, 0.9, 1.1, 0.75, 1, 0.5, "least_squares", 0, 0.9, out hv_Row, out hv_Column,
                out hv_Angle, out hv_Scale, out hv_Score);
            HOperatorSet.ClearShapeModel(hv_ModelID);

                ho_ImageReduced.Dispose();
                ho_Rectangle.Dispose();
            if (hv_Score.Length > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
            }
            catch
            {
                Log4Net.MsgInfo("模板匹配异常");
                return true;
            }


        }

        private bool Find_Model(string model, HObject image)
        {
            //try
            //{
            // Local iconic variables 

            // Local control variables 

            HTuple hv_ModelID = null, hv_Row = null, hv_Column = null;
            HTuple hv_Angle = null, hv_Scale = null, hv_Score = null;
            // Initialize local and output iconic variables 
            HOperatorSet.ReadShapeModel(model, out hv_ModelID);
            HOperatorSet.FindScaledShapeModel(image, hv_ModelID, -0.39,
                0.78, 0.9, 1.1, 0.75, 1, 0.5, "least_squares", 0, 0.9, out hv_Row, out hv_Column,
                out hv_Angle, out hv_Scale, out hv_Score);
            HOperatorSet.ClearShapeModel(hv_ModelID);
            if (hv_Score.Length > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
            //}
            //catch
            //{
            //    Log4Net.MsgInfo("模板匹配异常");
            //    return true;
            //}


        }
    }
}
